package com.hup.utils.commons.start;

import com.hup.utils.commons.TextUtil;
import com.hup.utils.commons.exception.AppExceptionHandler;
import com.hup.utils.commons.exception.ErrInfo;
import com.hup.utils.commons.interfaces.Runners.RunAndThrowable;
import com.hup.utils.commons.start.StartUpProcessor.StartUpProcessorHandler;
import lombok.extern.log4j.Log4j2;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;

/**
 * 程序启动窗
 *
 * @author hugan
 * @date 2019/8/18
 */
@Log4j2
public class StartUpWindow extends JWindow implements StartUpProcessorHandler {

    /**
     * 参考类: {@link StartupInfo},{@link AppInfo}
     * <pre>
     * 启动web程序:
     *   SpringApplication.run(App.class, args);
     * 启动普通程序:
     *   //https://my.oschina.net/u/3768341/blog/1819081
     *   SpringApplicationBuilder builder = new SpringApplicationBuilder(App.class);
     *   ApplicationContext context = builder.headless(false).run(args);
     * </pre>
     */
    public static void startUp(RunAndThrowable runnable) {
        /*
        如果项目依赖了spring-boot-devtools;
        会导致main方法被加载两次;使用的是两个不同的classLoader,会导致static代码块/变量,单例,都有影响!
        这里会导致:catch中捕获到SilentExitException,StartUpProcessor.startUpFinish();会抛异常!
        目前不处理,不建议引入devtools
         */
        StartUpWindow startUpWindow = null;
        try {
            StartupInfo.init();
            startUpWindow = new StartUpWindow(StartupInfo.getApplicationChName(), StartupInfo.getVersion());
            StartUpProcessor.registerHandler(startUpWindow);
            runnable.run();
            log.info("启动成功");
            startUpWindow.startUpFinish();
        } catch (Throwable e) {
            if (startUpWindow != null) {
                startUpWindow.startUpFinish();
            }
            ErrInfo errInfo = AppExceptionHandler.handleNoLog(e);
            log.error("启动失败:{}", errInfo);
            DialogHelper.errExit(errInfo.toString()).title("启动失败").show(startUpWindow);
        }
        StartUpProcessor.startUpFinish();
    }

    private JProgressBar progressBar;
    private int totalProgress = 28;

    private StartUpWindow(String appName, String version) {
        setupUI(appName, version);

        float screenScale = LookThemeUtil.getScreenScale();
        setMinimumSize(new Dimension((int) (218 * screenScale), (int) (68 * screenScale)));
        pack();
        setAlwaysOnTop(true);
        setLocationRelativeTo(null);

        progressBar.setMaximum(totalProgress);
        progressBar.setValue(0);
        setVisible(true);
    }

    private void setupUI(String appName, String version) {
        float screenScale = LookThemeUtil.getScreenScale();

        JPanel contentPane = new JPanel(new BorderLayout());
        contentPane.setBorder(new LineBorder(Color.gray));
        setContentPane(contentPane);

        JPanel panel = new JPanel(new BorderLayout());
        contentPane.add(panel, BorderLayout.CENTER);

        JLabel labAppName = new JLabel(appName);
        labAppName.setFont(new Font("黑体", Font.BOLD, LookThemeUtil.getDefaultScaledFontSize()));
        labAppName.setBorder(new EmptyBorder(0, (int) (30 * screenScale), 0, (int) (8 * screenScale)));
        panel.add(labAppName, BorderLayout.WEST);

        if (!TextUtil.isBlank(version)) {
            JLabel labVersion = new JLabel(version);
            labVersion.setFont(new Font("宋体", Font.PLAIN, (int) (13 * screenScale)));
            labVersion.setBorder(new EmptyBorder(0, 0, 0, (int) (30 * screenScale)));
            panel.add(labVersion, BorderLayout.CENTER);
        }

        JLabel labBootTag = new JLabel("启动中...");
        labBootTag.setFont(new Font("黑体", Font.PLAIN, (int) (12 * screenScale)));
        labBootTag.setBorder(new EmptyBorder(0, (int) (8 * screenScale), 0, 0));
        panel.add(labBootTag, BorderLayout.SOUTH);

        progressBar = new JProgressBar();
        contentPane.add(progressBar, BorderLayout.SOUTH);
    }

    private void startUpFinish() {
        dispose();
    }

    @Override
    public void onGetBeanTotal(int total) {
        log.debug("total={}", total);
        totalProgress = total;
        progressBar.setMaximum(totalProgress);
        progressBar.setValue(3);
    }

    @Override
    public void onBeanInited() {
        int progress = progressBar.getValue() + 1;
        log.debug("progress={}/{}", progress, totalProgress);
        progressBar.setValue(progress);
    }
}
